package gui;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;

import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.border.TitledBorder;

import types.DataSet;

import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;



public class OutputWindowSubGroups extends JFrame implements Printable  {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static JPanel panelButtons;
	private JList<?> listTests;
	private static JButton btnMatrix;
	
	private static int[] pageBreaks;  // array of page break line positions.
	private static int[] testsNumber;
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public OutputWindowSubGroups(final DataSet finalDataSet, final String path) {
		
		JFrame guiOutFrame = new JFrame();
		guiOutFrame.setIconImage(Toolkit.getDefaultToolkit().getImage(OutputWindowSubGroups.class.getResource("/images/OutputWin16.gif")));
		guiOutFrame.setAlwaysOnTop(true);
		guiOutFrame.setResizable(false);
        
        // frame properties
		guiOutFrame.setTitle("Groups of similar tests");
		guiOutFrame.setSize(600,500);
        
        // center the JFrame in the middle of the screen
		guiOutFrame.setLocationRelativeTo(null);
		
		final JPanel panelTests = new JPanel();
		panelTests.setBackground(Color.WHITE);
		final DefaultListModel listValues = new DefaultListModel();
		final JLabel lblMedoid = new JLabel("");
		lblMedoid.setForeground(new Color(0, 128, 0));
		lblMedoid.setFont(new Font("Tahoma", Font.PLAIN, 18));
		
		guiOutFrame.getContentPane().setLayout(new FormLayout(new ColumnSpec[] {
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("default:grow"),
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				FormFactory.DEFAULT_COLSPEC,},
			new RowSpec[] {
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("max(21dlu;default)"),
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("max(115dlu;default)"),
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("default:grow"),
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,}));
		
		JLabel lblSubGroupsResult = new JLabel("Groups of similar tests");
		lblSubGroupsResult.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/group16.png")));
		lblSubGroupsResult.setFont(new Font("Tahoma", Font.BOLD, 18));
		lblSubGroupsResult.setHorizontalAlignment(SwingConstants.CENTER);
		guiOutFrame.getContentPane().add(lblSubGroupsResult, "4, 2, 5, 4");
		
		JLabel lblSelectSubgroup = new JLabel("Select a sub-group: ");
		guiOutFrame.getContentPane().add(lblSelectSubgroup, "4, 10, right, default");
		
		// combo box sub-groups
		final JComboBox<String> comboSubGroups = new JComboBox<String>();
		for(int i=0	; i<finalDataSet.getSubSets().size()	; i++)
			comboSubGroups.addItem( "sg"+(i+1) );	// add items to the combo box
		
		guiOutFrame.getContentPane().add(comboSubGroups, "6, 10, fill, default");
		
		
		JButton btnSubGroup = new JButton("show tests");
		btnSubGroup.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				panelTests.setVisible(true);	// show tests in selected sub-group
				panelButtons.setVisible(true);  // show buttons print&save
				
				listValues.clear();	//clear list
				
				// add tests of specific sub-group
				int sgInd = comboSubGroups.getSelectedIndex();
				int sg_size = finalDataSet.getSubSetByIndex(sgInd).getSize();
				testsNumber = new int[sg_size];
				
				for(int i=0	; i<sg_size ; i++)
				{
					int t = finalDataSet.getSubSetByIndex(sgInd).getTestIndex(i);
					listValues.addElement( comboSubGroups.getSelectedItem() +"_test"+(t+1)+ "   " );
					
					testsNumber[i] = t+1;	// insert test number to array
				}
				
				lblMedoid.setText("The Medoid is: " +"sg"+(sgInd+1)+ "_test"+(finalDataSet.getSubSetByIndex(sgInd).getMedoidIndex()+1) );
				
				btnMatrix.setEnabled(true);
			}
		});
		guiOutFrame.getContentPane().add(btnSubGroup, "8, 10");
		
		JButton btnChart = new JButton("");
		btnChart.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/chart.png")));
		btnChart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				// create chart
				
				//Prepare the data set
			    DefaultPieDataset pieDataset = new DefaultPieDataset();
			    
			  
			    for(int i=0	; i<finalDataSet.getSubSets().size()	; i++)
			    	 pieDataset.setValue("Sub Group"+(i+1) , finalDataSet.getSubSetByIndex(i).getSize());
			    
			    //Create the chart
			    JFreeChart chart = ChartFactory.createPieChart3D(
			        "Sub Groups", pieDataset, true, true, true);
			    
			    //Render the frame
			    ChartFrame chartFrame = new ChartFrame("Sub Groups window", chart);
			    chartFrame.setVisible(true);
			    chartFrame.setSize(650, 500);
				
			}
		});
		
		guiOutFrame.getContentPane().add(btnChart, "10, 10");
		
		// matrix button
		btnMatrix = new JButton("");
		btnMatrix.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/table.png")));
		btnMatrix.setEnabled(false);
		btnMatrix.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				double[][] data = finalDataSet.getSubSetByIndex(comboSubGroups.getSelectedIndex()).getDistanceMatrix();
				double[][] d = new double[data.length+1][data.length+1];
				String[] h = new String[data.length+1];
				
				// headers
				for(int i=0; i<d.length; i++)	
				{
					if(i==0)	
					{
						h[i] = "test #";
						continue;
					}
					
					h[i] = "test "+ testsNumber[i-1]; 	// test num
				}
				
				// data
				for(int i=0; i<d.length; i++)	// rows
				{
					for(int j=0; j<d.length; j++)	// cols
					{
						if(i==0)
							d[i][j] = 0;	// init row[0]=0
						else
						{
							if((i-1)<data.length && (j)<data.length)
								d[i][j] = data[i-1][j];
						}
							
					}
				}

				MatrixWindow mw = new MatrixWindow(d,h,comboSubGroups.getSelectedItem().toString()); 
				mw.setVisible(true);
			}
		});
		
		
		guiOutFrame.getContentPane().add(btnMatrix, "12, 10");
		panelTests.setBorder(new TitledBorder(null, "", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		guiOutFrame.getContentPane().add(new JScrollPane(panelTests), "4, 13, 5, 7, fill, fill");
		FlowLayout fl_panelTests = new FlowLayout(FlowLayout.LEFT, 5, 5);
		fl_panelTests.setAlignOnBaseline(true);
		panelTests.setLayout(fl_panelTests);
		
		
		listTests = new JList(listValues);	// add values to list
		listTests.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent evt) {
				JList list = (JList)evt.getSource();
				if (evt.getClickCount() == 2) {	// 2-clicks
	            
		            // open new frame
		            JFrame newFrame = new JFrame(list.getSelectedValue().toString());
		            newFrame.setSize(400, 300);
		            JPanel panel = new JPanel();
		            newFrame.getContentPane().add(panel);
		            
		            int index = list.locationToIndex(evt.getPoint());	// selected test index
		            int sgInd = comboSubGroups.getSelectedIndex();		// selected sub-grop index
					String testStr = finalDataSet.getSubSetByIndex(sgInd).getElement(index);	// test
		            
		            JTextArea ta = new JTextArea( testStr ,2,60 );
		            ta.setWrapStyleWord(true); 
		            panel.add(new JScrollPane(ta));

		            newFrame.setAlwaysOnTop(true);
		            newFrame.pack();
		            newFrame.setVisible(true);
		        }
			}
		});
		listTests.setLayoutOrientation(JList.VERTICAL_WRAP);
		listTests.setFont(new Font("Tahoma", Font.PLAIN, 12));
		listTests.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		listTests.setVisibleRowCount(10);
		panelTests.add( listTests );
		
		
		guiOutFrame.getContentPane().add(lblMedoid, "6, 20");
		
		
		panelButtons = new JPanel();
		panelButtons.setVisible(false); // hide buttons print&save
		guiOutFrame.getContentPane().add(panelButtons, "2, 24, 7, 1, center, bottom");
		panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.X_AXIS));
		
		JButton btnPrintResults = new JButton("Print results ");
		final PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(this);
		btnPrintResults.addActionListener(new ActionListener() { 
					public void actionPerformed(ActionEvent e) {
				         boolean ok = job.printDialog();
				         if (ok) {
				             try {
				                  job.print();              
				             } catch (PrinterException ex) {
				              /* The job did not successfully complete */
				             }
				         }
				        
				    } 
        });
		
		btnPrintResults.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/print16.gif")));
		panelButtons.add(btnPrintResults);
		
		Component horizontalStrut = Box.createHorizontalStrut(20);
		panelButtons.add(horizontalStrut);
		
		JButton btnSaveToFile = new JButton("Save results to file");
		btnSaveToFile.setIcon(new ImageIcon(OutputWindowSubGroups.class.getResource("/images/disk16.gif")));
		btnSaveToFile.addActionListener(new ActionListener() { 
			public void actionPerformed(ActionEvent e) {
				int sgInd = comboSubGroups.getSelectedIndex();
				PrintWriter writer = null;
				try {
					writer = new PrintWriter(path+"\\SubGroup"+(sgInd+1)+".txt", "UTF-8");
					
				} catch (FileNotFoundException | UnsupportedEncodingException e1) {
					e1.printStackTrace();
				}
				for(int j=0; j<finalDataSet.getSubSetByIndex(sgInd).getSize();j++){
					int t = finalDataSet.getSubSetByIndex(sgInd).getTestIndex(j);
					String test = finalDataSet.getSubSetByIndex(sgInd).getElement(j);
					writer.println("Test "+t);
					writer.println(test);
					writer.println();
				}
				writer.println();
				writer.close();
		    } 
		});
		panelButtons.add(btnSaveToFile);
		      
        //make sure the JFrame is visible
		guiOutFrame.setVisible(true);

	}
	
	
	
	public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
		Font font = new Font("Tahoma", Font.PLAIN, 12);
		FontMetrics metrics = g.getFontMetrics(font);
		int lineHeight = metrics.getHeight();

		if (pageBreaks == null) {
			int linesPerPage = (int)(pf.getImageableHeight()/lineHeight);
			int numBreaks = listTests.getModel().getSize() / linesPerPage;
			pageBreaks = new int[numBreaks];
			
			for (int b=0; b<numBreaks; b++) {
				pageBreaks[b] = (b+1)*linesPerPage;
			}
		}

		if (pageIndex > pageBreaks.length) {
			return NO_SUCH_PAGE;
		}
		
		Graphics2D g2d = (Graphics2D)g;
		g2d.translate(pf.getImageableX(), pf.getImageableY());

	int y = 0; 
	int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex-1];
	int end = (pageIndex == pageBreaks.length) ? listTests.getModel().getSize() : pageBreaks[pageIndex];
	
	for (int line=start; line<end; line++) {
		y += lineHeight;
		
		g.drawString(listTests.getModel().getElementAt(line).toString(), 0, y);
	}
	
	return PAGE_EXISTS;
		
	}
	
    
//	print one page only!!!	
//		public int print(Graphics g, PageFormat pf, int page) throws	PrinterException {
//		
//		if (page > 0) { /* We have only one page, and 'page' is zero-based */
//			return NO_SUCH_PAGE;
//		}
//		
//		/* User (0,0) is typically outside the imageable area, so we must
//		* translate by the X and Y values in the PageFormat to avoid clipping
//		*/
//		Graphics2D g2d = (Graphics2D)g;
//		g2d.translate(pf.getImageableX(), pf.getImageableY());
//		
//		/* Now print the lists  */
//		listTests.setVisibleRowCount(40);
//		listTests.setVisibleRowCount(40);
//		listTests.print(g);
//		listTests.setVisibleRowCount(10);
//		
//		/* tell the caller that this page is part of the printed document  */
//		return PAGE_EXISTS;
//	}
}
